package com.demo.common.monitor.impl;

import java.lang.management.*;

/**
 * Demo code which plots the memory usage by all memory pools. The memory usage
 * is sampled at some time interval using java.lang.management API. This demo
 * code is modified based java2d MemoryMonitor demo.
 */
public class MemoryMonitor {

	// Get memory pools.
	static java.util.List<MemoryPoolMXBean> mpools = ManagementFactory.getMemoryPoolMXBeans();
	// Total number of memory pools.
	static int numPools = mpools.size();
	private int usageHistCount = 250;
	// 当前使用量
	private float usedMem[][];
	// 各指标最大使用量
	private float maxMem[];
	// 记录当前运行到第N个,如果超过usageHistCount上限,则从头替换
	private int ptNum[];
	// 指标名称
	private String ptName[];
	public MemoryMonitor() {
		usedMem = new float[numPools][];
		ptNum = new int[numPools];
		ptName = new String[numPools];
		maxMem = new float[numPools];
	}
	
	/**
	 * 
	 */
	public void destroy() {
		usedMem = new float[numPools][];
		ptNum = new int[numPools];
		ptName = new String[numPools];
		maxMem = new float[numPools];
	}

	/**
	 * 取得内存指标数据量(实时全量)
	 * @return float[][]
	 */
	public void paint() {
		for (int k = 0; k < numPools; k++) {
			plotMemoryUsage(k);
		}
		//System.out.print("usedMem:" + usedMem + " ptNum:" + ptNum + "\n");
		//return this.usedMem;
	}
	
	private void plotMemoryUsage(int npool) {

		MemoryPoolMXBean mp = mpools.get(npool);
		float usedMemory = mp.getUsage().getUsed();
		float totalMemory = mp.getUsage().getMax();
			//System.out.print(mp.getName());
		// Print the memory used by this memory pool.
		// .. Memory Used ..
		String usedStr = String.valueOf((int) usedMemory / 1024) + "K used";
		String maxStr = String.valueOf((int)totalMemory/1024) + "K Max ";
		String freeStr =  String.valueOf((int)(totalMemory - usedMemory)/1024) + "K free ";
		// .. Memory Free ..
		//float MemUsage = (float) (((totalMemory - usedMemory) / totalMemory) * 10);
		
		System.out.print("[" + mp.getName() + "] usedMemory:" + usedStr + " totalMemory:" + maxStr + " freeStr:" + freeStr+"\n");

		// Plot memory usage by this memory pool.
		if (usedMem[npool] == null) {
			usedMem[npool] = new float[usageHistCount];
			ptNum[npool] = 0;
		}

		// save memory usage history.
		usedMem[npool][ptNum[npool]] = usedMemory;

		if (ptNum[npool] + 2 == usedMem[npool].length) {
			// throw out oldest point
			for (int j = 1; j < ptNum[npool]; j++) {
				usedMem[npool][j - 1] = usedMem[npool][j];
			}
			--ptNum[npool];
		} else {
			ptNum[npool]++;
		}
	}

	/**
	 * 使用内存情况
	 * @return float[][]
	 */
	public float[][] getMemoryData() {
		paint();
		return this.usedMem;
	}
	
	/**
	 * 取得当前时间点的内存使用情况
	 * @return float[][] ：[2000000001(时间),879840.0(用量)]
	 */
	public float[] getMemoryPoint(int npool) {
		float[] useMem = new float[2];
		MemoryPoolMXBean mp = mpools.get(npool);
		float usedMemory = mp.getUsage().getUsed();
		//float totalMemory = mp.getUsage().getMax();
		useMem[0] = System.currentTimeMillis();
		useMem[1] = usedMemory;
		
		return useMem;
	}
	
	public float[][] getMemoryPoint() {
		float[][] useMem = new float[numPools][2];
		for (int i = 0; i < numPools; i ++) {
			MemoryPoolMXBean mp = mpools.get(i);
			float usedMemory = mp.getUsage().getUsed();
			//float totalMemory = mp.getUsage().getMax();
			useMem[i][0] = System.currentTimeMillis();
			useMem[i][1] = usedMemory;
		}
		return useMem;
	}
	
	/**
	 * 最大内存
	 * @return float[] 
	 */
	public float[] getMemoryMax() {
		maxMem = new float[numPools];
		for (int i = 0; i < numPools; i ++) {
			MemoryPoolMXBean mp = mpools.get(i);
			maxMem[i] = mp.getUsage().getMax();
		}
		return maxMem;
	}
	/**
	 * 取得内存指标名称
	 * @return String[]
	 */
	public String[] getPtName() {
		for (int i = 0; i < numPools; i ++) {
			ptName[i] = mpools.get(i).getName();
		}
		return ptName;
	}
	
	public static void main(String s[]) {
		final MemoryMonitor demo = new MemoryMonitor();
		// 数组下标 0:Code Cache;1:PS Eden Space;2:PS Surivor Space;3:PS Old Gen;4:PS Perm Gen;
		demo.getMemoryData();
		demo.getMemoryData();
		demo.getMemoryData();
		demo.getMemoryData();
		demo.getPtName();
	}

}
